using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.Commands;
using Microsoft.Practices.CompositeUI.UIElements;
using Microsoft.Practices.ObjectBuilder;
using NUnit.Framework;
using Rhino.Mocks;
using SCSFContrib.CompositeUI.WPF;
using SCSFContrib.CompositeUI.WPF.Activation;
using SCSFContrib.CompositeUI.WPF.BuilderStrategies;
using SCSFContrib.CompositeUI.WPF.CommandAdapters;
using SCSFContrib.CompositeUI.WPF.UIElements;
using SCSFContrib.CompositeUI.WPF.Visualizer;

namespace SCSFContrib.CompositeUI.WPF.UnitTest
{
	[TestFixture]
	public sealed class WindowsApplicationTest : UnitTest
	{
		private WindowsApplication<WorkItem, TestableRootWorkItem> _windowsApplication;

		protected override void SetUpCore()
		{
			base.SetUpCore();
			_windowsApplication = Mocks.PartialMock<WindowsApplication<WorkItem, TestableRootWorkItem>>();
			Mocks.ReplayAll();
		}

		[Test]
		public void Constructor_ShouldSetVisualizerType()
		{
			Assert.AreEqual(typeof(WindowsVisualizer), GetPrivateMemberValue<Type>(_windowsApplication, "VisualizerType"));
		}

		[Test]
		public void Constructor_ShouldConfigureSynchronizationContext()
		{
			Assert.IsNotNull(SynchronizationContext.Current);
			Assert.AreEqual(typeof(DispatcherSynchronizationContext), SynchronizationContext.Current.GetType());
		}

		[Test]
		public void AddBuilderStrategies_ShouldAddRequiredStrategies()
		{
			Builder builder = new Builder();
			InvokePrivateMethod<object>(_windowsApplication, "AddBuilderStrategies", builder);
			IBuilderStrategyChain chain = builder.Strategies.MakeStrategyChain();
			IBuilderStrategy builderStrategy = chain.Head;
			List<Type> strategyTypes = new List<Type>();

			while (builderStrategy != null)
			{
				strategyTypes.Add(builderStrategy.GetType());
				builderStrategy = chain.GetNext(builderStrategy);
			}

			Assert.IsTrue(strategyTypes.Contains(typeof(WindowsServiceStrategy)));
			Assert.IsTrue(strategyTypes.Contains(typeof(FrameworkElementActivationStrategy)));
			Assert.IsTrue(strategyTypes.Contains(typeof(FrameworkContentElementActivationStrategy)));
			Assert.IsTrue(strategyTypes.Contains(typeof(FrameworkElementSmartPartStrategy)));
		}

		[Test]
		public void AddServices_ShouldAddRequiredServices()
		{
			Mocks.BackToRecord(_windowsApplication);
			InvokePrivateMethod<object>(_windowsApplication, "Start", null);
			LastCall.Repeat.Once();
			Mocks.ReplayAll();

			Builder builder = new Builder();
			_windowsApplication.Run();
			Assert.IsTrue(_windowsApplication.RootWorkItem.Services.Contains<IFrameworkElementActivationService>());
			Assert.IsTrue(_windowsApplication.RootWorkItem.Services.Contains<IFrameworkContentElementActivationService>());
		}

		[Test]
		public void AfterShellCreated_ShouldRegisterRequiredAdapters()
		{
			Mocks.BackToRecord(_windowsApplication);
			InvokePrivateMethod<object>(_windowsApplication, "Start", null);
			LastCall.Repeat.Once();
			Mocks.ReplayAll();

			Builder builder = new Builder();
			_windowsApplication.Run();
			ICommandAdapterMapService commandAdapterMapService = _windowsApplication.RootWorkItem.Services.Get<ICommandAdapterMapService>();
			Assert.AreEqual(typeof(UIElementCommandAdapter), commandAdapterMapService.CreateAdapter(typeof(UIElement)).GetType());
			IUIElementAdapterFactoryCatalog uiElementAdapterFactoryCatalog = _windowsApplication.RootWorkItem.Services.Get<IUIElementAdapterFactoryCatalog>();
			List<IUIElementAdapterFactory> factories = new List<IUIElementAdapterFactory>(uiElementAdapterFactoryCatalog.Factories);

			Assert.IsTrue(factories.FindAll(delegate(IUIElementAdapterFactory factory)
			{
				return factory.GetType() == typeof(ItemsControlUIAdapterFactory);
			}).Count == 1);
		}
	}
}
